#pragma once

#include "sqlite3.h"

using namespace Windows::Storage;
using namespace Windows::ApplicationModel;
using namespace Platform;
using namespace concurrency;
using namespace Windows::Foundation;

namespace SQLite 
{
	ref class Statement;
	public ref class Database sealed 
	{
		friend Statement;
	private:
		sqlite3* db;
		String^ _path;

		bool CloseDB()
		{
			if (db != NULL) 
			{
				int result = sqlite3_close(db);
				if(result == SQLITE_OK)
				{
					db = NULL;
					return true;
				}
				else
				{
					return false;
				}
			}

			return true;
		}

	public:
		property bool Ready;
		property String^ Path
		{
			String^ Path::get() 
			{
				return _path;
			}
		}

		Database(Platform::String^ path)
		{
			_path = Package::Current->InstalledLocation->Path + "\\" + path;

			OutputDebugString(_path->Data());
			int rc = sqlite3_open16(_path->Data(), &db);
			Ready = rc == SQLITE_OK;
		}
		Database(Platform::String^ path, bool writablePath) 
		{
			if (writablePath)
			{
				_path = ApplicationData::Current->LocalFolder->Path + "\\" + path;
			}
			else
			{
				_path = Package::Current->InstalledLocation->Path + "\\" + path;
			}
			OutputDebugString(_path->Data());
			int rc = sqlite3_open16(_path->Data(), &db);
			Ready = rc == SQLITE_OK;
		}

		IAsyncAction^ StartClean()
		{
			return create_async([this] () -> void
			{
				CloseDB();
				auto file = create_task(StorageFile::GetFileFromPathAsync(_path)).get();
				OutputDebugString(_path->Data());
				try
				{
					create_task(file->DeleteAsync(Windows::Storage::StorageDeleteOption::PermanentDelete)).get();
					OutputDebugString(_path->Data());
					int rc = sqlite3_open16(_path->Data(), &db);
					Ready = rc == SQLITE_OK;
				}
				catch (Platform::COMException^ e)
				{
					//Example output: The system cannot find the specified file.
					OutputDebugString(e->Message->Data());
				}
			});
		}

		virtual ~Database() 
		{
			CloseDB();
		}


		Statement^ PrepareStatement(Platform::String^ cmd);
	};
}